/*
 * Copyright (c) 2012, SimmerVoice
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 * 
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in
 * the documentation and/or other materials provided with the distribution.
 * Neither the name of the UTEP nor the names of its contributors
 * may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * File:         com.simmervoice.simmerhome SimmerHomeActivity.java
 * Created:      Nov 2, 2012 10:33:18 PM
 * 
 * Version History
 * v1.0: 10/01/2012- Initial Elishiah Miller
 */
package com.sizzlevoice.sizzlehome;


import java.io.File;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.ispeech.FreeformType;
import org.ispeech.SpeechRecognizer;
import org.ispeech.SpeechRecognizerEvent;
import org.ispeech.SpeechResult;
import org.ispeech.SpeechSynthesis;
import org.ispeech.SpeechSynthesisEvent;
import org.ispeech.error.BusyException;
import org.ispeech.error.InvalidApiKeyException;
import org.ispeech.error.NoNetworkException;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

/**
 * MainActivity 
 * @author Elishiah Miller
 *
 */
public class SizzleHomeActivity extends Activity {
	
	/**Used to see process in LogCat window**/
	private static final String TAG = "SizzleVoice";
	/**synthesis object to use TTS**/
	private SpeechSynthesis synthesis;
	/**speech recognizer to recognize utterance**/
	private SpeechRecognizer recognizer;
	/**The type of voice to be used**/
	private final String Sythesisvoice = "usenglishfemale"; 
	/**store state of the synthesis**/
	private boolean playFlag = false;
	private boolean searchFlag = false;
	private boolean greetingFlag = false;
	/**store the recognized text**/
	private String recognizedText = "";
	int choice=1;	
	private Context _context;
	private ReadXMLFile XMLfile;
	String[] fileName;
	String[] recipeNames;
	String[] directionSteps;
	String path;
	String greetRecText;
	List<String> l;
	int counter = 1;
	
	/**
	 * This method is called when the application is first started
	 */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simmer_home);
        
        _context = this.getApplicationContext();
        
        /**create the synthesis object**/
        prepareTTSEngine();
        
        /**create the recognizer object**/
        setupFreeFormDictation();
        
        /**create button listeners**/
        buttons();
    }
    
    private void buttons(){
        
        /**searchBtn
         * This button should only be used to help the user search for recipes**/
        Button searchBtn = (Button) findViewById(R.id.search);
        searchBtn.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				choice=1;
				searchFlag=true;
				greetingFlag=true;
				//clear all commands
				recognizer.clearCommand();
				//start the recognizer after a greeting message
				playFlag=true;
				
				//create grammar for search
				
				File sdCard = Environment.getExternalStorageDirectory();
				File directory = new File (sdCard.getAbsolutePath());
				path = sdCard.getAbsolutePath() + "/Recipes/";
				
				
				//Path and name of XML file
				File file = new File(directory,"/Recipes/");
				
				//get the file name of he recipes
				int numFiles=0;
		    	for (File f : file.listFiles()) {
		    	    if (f.isFile()){
		    	    	numFiles++;
		    	    }
		    	}
		    	fileName = new String[numFiles];
		    	recipeNames = new String[numFiles];
		    	
		    	int i =0;
		    	for (File f : file.listFiles()) {
		    	    if (f.isFile()){
		    	    	String name = f.getName();
		    	    	Log.d("Recipe Name:", name);
		    	    	fileName[i]=name;
		    	    	i++;
		    	    }
		    	}
		    	
				//get the recipe names
		    	Log.d("fileNameSize", Integer.toString(fileName.length));
		    	for(int j=0; j < fileName.length;j++){
		    			XMLfile = new ReadXMLFile(path + fileName[j]);
			    		recipeNames[j]=XMLfile.getRecipeNames().get(0);
			    		Log.d("RECIPE NAME", recipeNames[j]);
		    	}
		    	
				
				//String[] recipes = new String[]{"vanilla almond orange cloud cookies", "Spice Rubbed Turkey"};
				//add the grammar to the recognizer
				recognizer.setTimeout(3000000);
				recognizer.addCommand(recipeNames);
				
				//Tell user recipe names
				String recipeNameList="";
				for(int j=0; j<recipeNames.length; j++){
					recipeNameList = recipeNameList + " ," + recipeNames[j];
				}
				
				//create the greeting message
				String greeting = "Please say one of the following recipe names" + recipeNameList;
				//use TTS to say greeting
				synthessize(greeting);
				}
			});
        
      //recipeBtn
        Button recipeBtn = (Button) findViewById(R.id.addrecipe);
        recipeBtn.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				Intent myIntent = new Intent(_context, CreateRecipeActivity.class);
				startActivity(myIntent);
				}
			});
        
        //startBtn
        Button startBtn = (Button) findViewById(R.id.start);
        startBtn.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				if(searchFlag==true){
					englishPersona();
					systemDialog();
				}
				}
			});
		
	}

	/**
     * This method is called every time this activity is called into view
     */
    public void onStart(){
    	super.onStart();
    	String greeting = "Click search to find a recipe.";
		synthessize(greeting);
    }
    
    /**Define how the synthesis sounds**/
    private void englishPersona(){
		synthesis.setVoiceType(Sythesisvoice);
		synthesis.clearOptionalCommand();
		synthesis.addOptionalCommand("speed", "0");
		synthesis.addOptionalCommand("pitch", "110");
    }
    
    /**Use TTS to say text**/
    private void synthessize(String text) {
    	try {
			String ttsText = text;
			synthesis.speak(ttsText);

		} catch (BusyException e) {
			Log.e(TAG, "SDK is busy");
			e.printStackTrace();
			Toast.makeText(this.getApplicationContext(), "ERROR: SDK is busy", Toast.LENGTH_LONG).show();
		} catch (NoNetworkException e) {
			Log.e(TAG, "Network is not available\n" + e.getStackTrace());
			Toast.makeText(this.getApplicationContext(), "ERROR: Network is not available", Toast.LENGTH_LONG).show();
		}
	}
    
    /**Control the flow of the dialog**/
	protected void systemDialog() {
		choice=2;
		greetingFlag=false;
		counter=1;
		//ask user for response
				//clear all commands
				recognizer.clearCommand();
				//start the recognizer after a greeting message
				playFlag=true;
				//create grammar for greeting
				String[] recipes = new String[]{"yes", "no", "help", "cancel"};
				//add the grammar to the recognizer
				recognizer.setTimeout(3000000);
				recognizer.addCommand(recipes);
				
				//Ingredients
				XMLfile = new ReadXMLFile(path + greetRecText + ".xml");
				l = XMLfile.getIngAndDir(greetRecText);
				String ingredients = l.get(0);
				String directions = l.get(1);
				createSteps(directions);
				synthessize(greetRecText+" ingredients include," + ingredients + "," +
						"Do you have the ingredients?");
	}

	private void createSteps(String directions) {
		 String text = directions;
		    String[] tokens = text.split("\\. ");
		    int i=0;
		    //get the number of steps.
		    for (String token : tokens) {
		        //System.out.println("[" + token + "]");
		    	i++;
		    }	
		    directionSteps = new String[i];
		    i=0;
		    for (String token : tokens) {
		    	directionSteps[i]=token;
		    	i++;
		        Log.d("TOKEN", token);
		    }	
	}

	/**
     * This method can be used to add option to the title bar
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_simmer_home, menu);
        return true;
    }
    
    /**
     * Instantiates synthesis
     */
    private void prepareTTSEngine() {
		try {
			synthesis = SpeechSynthesis.getInstance(this);
			SpeechSynthesisEvent s;

			synthesis.setSpeechSynthesisEvent(new SpeechSynthesisEvent() {

				public void onPlaySuccessful() {
					Log.i(TAG, "onPlaySuccessful");
					if(playFlag==true){
						startRecognition();
					}
					playFlag = false; 
					Log.i(TAG, Boolean.toString(playFlag));
				}

				public void onPlayStopped() {
					Log.i(TAG, "onPlayStopped");
					
				}

				public void onPlayFailed(Exception e) {
					Log.e(TAG, "onPlayFailed");
					e.printStackTrace();
				}

				public void onPlayStart() {
					Log.i(TAG, "onPlayStart");
				}

				@Override
				public void onPlayCanceled() {
					Log.i(TAG, "onPlayCanceled");
				}
				
				
			});

		} catch (InvalidApiKeyException e) {
			Log.e(TAG, "Invalid API key\n" + e.getStackTrace());
			Toast.makeText(this.getApplicationContext(), "ERROR: Invalid API key", Toast.LENGTH_LONG).show();
			playFlag = false; 
		}

	}
    
    /**
     * Set free form dictation
     */
    private void setupFreeFormDictation() {
		try {

			recognizer = SpeechRecognizer.getInstance(this.getApplicationContext());
			//recognizer.setFreeForm(FreeformType.FREEFORM_DICTATION);
			recognizer.setLocale("en-US");

		} catch (InvalidApiKeyException e) {
			e.printStackTrace();
		}
	}
    
    /**Start the recognition and set the recognized text to the results of the recognizer**/
	private void startRecognition() {
		
		try {
			recognizer.startRecord(new SpeechRecognizerEvent() {
				@Override
				public void onRecordingComplete() {
					Log.d(TAG, "Recording completed.");		
				}
				
				/**Get the recognized text**/
				@Override
				public void onRecognitionComplete(SpeechResult result) {
					Log.d(TAG, "Recognition complete");
					
					if(result != null){
					/**If something was recognized get the text**/
					if (result.getText().equalsIgnoreCase("")) {
						Log.d(TAG, "Result is null...");
						playFlag=true;
						synthessize("I didn't get that");
						}else{
							Log.d(TAG, "Text Result:" + result.getText());
							Log.d(TAG, "Text Conf:" + result.getConfidence());
							recognizedText = result.getText();	
							if(greetingFlag==true){
								greetRecText = recognizedText;
							}
							
							if(choice==1){
								synthessize("Your recipe for "+ recognizedText + "is ready. Click start.");
							}else if(choice==2){
								if(recognizedText.equalsIgnoreCase("yes")){
									//say the directions one by one
									recognizer.clearCommand();
									//start the recognizer after a greeting message
									playFlag=true;
									//create grammar for greeting
									String[] recipes = new String[]{"next", "help", "cancel"};
									//add the grammar to the recognizer
									recognizer.setTimeout(3000000);
									recognizer.addCommand(recipes);
									
									//First Direction
									synthessize(directionSteps[0]);
								}else if (recognizedText.equalsIgnoreCase("no")){
									playFlag=false;
									synthessize("Ok! I'll wait while you get them. " +
											"Click start to continue and hear the ingredients again");
								}else if(recognizedText.equalsIgnoreCase("next")){
									//Ingredients
									if(counter<directionSteps.length){
										playFlag=true;
										synthessize(directionSteps[counter]);
										counter++;
									}else{
										playFlag=false;
										synthessize("Thats the end of your recipe");
									}
									
								}else if(recognizedText.equalsIgnoreCase("help")){
									playFlag=true;
									synthessize("You can say, next, to hear the next recipe!" +
											"or, you can say, cancel, to cancel");
								}else if(recognizedText.equalsIgnoreCase("cancel")){
									playFlag=false;
									synthessize("Your recipe was canceled, thank you");
								}
							}
							
						}
					}
				}

				@Override
				public void onRecordingCancelled() {
					Log.d(TAG, "Recording cancelled.");
				}

				@Override
				public void onError(Exception exception) {
					Log.d(TAG, "**ERROR: " + exception.getMessage());
					exception.printStackTrace();
					playFlag=true;
					synthessize("I didn't get that");
				}
			});
		} catch (BusyException e) {
			e.printStackTrace();
		} catch (NoNetworkException e) {
			e.printStackTrace();
		}
	}
}
